package cn.wlinker.driver.common.utils;

import cn.hutool.core.text.CharSequenceUtil;
import cn.wlinker.driver.common.constant.Constant;
import cn.wlinker.driver.common.exception.DriverInitException;
import cn.wlinker.driver.common.exception.IncompleteInfoException;

/**
 * 驱动连接接口
 *
 * @param <C> 连接信息对象
 * @param <T> 连接成功后的传输对象
 *
 * @author gxsjx
 * @version 1.0
 * @date 2023/7/14
 * Copyright © wlinker.cn
 */
public interface IConnectHelper<C, T> {

    String getConnectionKey(C connectBean);

    /**
     * 连接
     * @param connectBean 连接信息对象
     * @return 连接成功后的传输对象
     * @throws Exception 连接异常
     */
    T connect(C connectBean) throws Exception;

    /**
     * 判断连接是否成功
     * @param connectBean 连接信息对象
     * @return 连接是否成功
     */
    boolean isConnected(C connectBean);

    /**
     * 断开连接
     * @param connectBean
     * @return
     */
    boolean disconnect(C connectBean);

    default String getCacheKey(C connectBean) {
        String simpleName = getClass().getSimpleName();
        String connectionKey = getConnectionKey(connectBean);
        return CharSequenceUtil.format("{}:{}", simpleName, connectionKey);
    }

    /**
     * 获取连接对象
     * @param connectBean
     * @return
     * @throws Exception
     */
    default T getConnection(C connectBean) throws Exception {
        synchronized (this) {
            if (connectBean == null) {
                throw new IncompleteInfoException("连接信息不能为空");
            }
            T connection = ConnectionCacheUtils.get(getCacheKey(connectBean));
            if (connection != null) {
                return connection;
            }
            try {
                connection = connect(connectBean);
                for (int i = 1; i <= Constant.RETRIES; i++) {
                    Boolean connected = isConnected(connectBean);
                    if (Boolean.TRUE.equals(connected)) {
                        break;
                    }
                    Thread.sleep(Constant.TIMEOUT_MS);
                }
            } catch (Exception e) {
                throw new DriverInitException("创建连接失败", e);
            }
            ConnectionCacheUtils.put(getCacheKey(connectBean), connection);
            return connection;
        }
    }
}
